home *** CD-ROM | disk | FTP | other *** search
- Subject: v21i096: An Automounter for NFS systems, Part08/13
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 588935f5 bebcb818 9ce08e0c 4e7e876d
-
- Submitted-by: Jan-Simon Pendry <jsp@doc.ic.ac.uk>
- Posting-number: Volume 21, Issue 96
- Archive-name: amd/part08
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 8 (of 13)."
- # Contents: examples/amd.homes mtab.c opts.c srvr_nfs.c
- # Wrapped by rsalz@papaya.bbn.com on Tue Apr 10 15:12:09 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'examples/amd.homes' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'examples/amd.homes'\"
- else
- echo shar: Extracting \"'examples/amd.homes'\" \(12180 characters\)
- sed "s/^X//" >'examples/amd.homes' <<'END_OF_FILE'
- X# /homes
- Xzmacy26 -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/zmacy26 \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xkevin -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/kpt \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xgrace -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/grace \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xaudit type=link;fs=/etc/security/audit
- Xygal -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=samson/ygal \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xacwf -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/acwf \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xrgc -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/rgc \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xlsh -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/lsh \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xjsp -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=jsp \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xjpr -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/jpr \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xjjc -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=genesis/jjc \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xids -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=samson/ids \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xmb -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/mb \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xdaemon type=link;fs=/
- Xteb -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=teb \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xshc -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=shc \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xmwg -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=mwg \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xmrs -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=mrs \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xjfc -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/jfc \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xdme -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=dme \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xccm -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/ccm \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xpt -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=dov/pt \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xds -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/ds \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xdg -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=dov/dg \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xwmvh -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=wmvh \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xroot type=link;fs=/
- Xlmjm -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/lmjm \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xsjk -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/sjk \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xmdr -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=mdr \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xkdr -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=kdr \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xbrg -opts=rw,grpid,nosuid;rfs=/home/gummo;sublink=users/brg \
- X host=!gummo;type=nfs;rhost=gummo \
- X host=gummo;type=ufs;dev=/dev/xy0g
- Xadh -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=adh \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xjs -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=samson/js \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xca -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=diadem/ca \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xbh -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/bh \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xnobody type=link;fs=/
- Xingres type=link;fs=/usr/ingres
- Xtsem -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=genesis/tsem \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xpm2 -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=pm2 \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xsm -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/sm \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xpm -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=pm \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xmd -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=md \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xjg -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=genesis/jg \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xphjk -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/phjk \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xiccp -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=samson/iccp \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xsza -opts=rw,grpid,nosuid;rfs=/home/ganymede;sublink=sza \
- X host=!ganymede;type=nfs;rhost=ganymede \
- X host=ganymede;type=ufs;dev=/dev/xy0h
- Xclh -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/clh \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xnd -opts=rw,grpid,nosuid;rfs=/home/gummo;sublink=users/nd \
- X host=!gummo;type=nfs;rhost=gummo \
- X host=gummo;type=ufs;dev=/dev/xy0g
- Xmg -opts=rw,grpid,nosuid;rfs=/home/ganymede;sublink=mg \
- X host=!ganymede;type=nfs;rhost=ganymede \
- X host=ganymede;type=ufs;dev=/dev/xy0h
- Xbp -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/bp \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xsync type=link;fs=/
- Xnews type=link;fs=/var/spool/news
- Xshb -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/shb \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xrjq -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=rjq \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xfst -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=fst \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xeaa -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=dov/eaa \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xsw -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/sw \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xhf -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=genesis/hf \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xlkcl -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=lkcl \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xchlo -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=samson/chlo \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xesh -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/esh \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xtm -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/tm \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xok -opts=rw,grpid,nosuid;rfs=/home/ganymede;sublink=ok \
- X host=!ganymede;type=nfs;rhost=ganymede \
- X host=ganymede;type=ufs;dev=/dev/xy0h
- Xja -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/ja \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xdp -opts=rw,grpid,nosuid;rfs=/home/gummo;sublink=usersdiana \
- X host=!gummo;type=nfs;rhost=gummo \
- X host=gummo;type=ufs;dev=/dev/xy0g
- Xzmact03 -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/zmact03 \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xuucp type=link;fs=/var/spool/uucppublic
- Xsme -opts=rw,grpid,nosuid;rfs=/home/ganymede;sublink=sme \
- X host=!ganymede;type=nfs;rhost=ganymede \
- X host=ganymede;type=ufs;dev=/dev/xy0h
- Xrjc -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/rjc \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xpdg -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=samson/pdg \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xdgb -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=dgb \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xdds -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=genesis/dds \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xih -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/ih \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xumacd20 -opts=rw,grpid,nosuid;rfs=/home/ganymede;sublink=umacd20 \
- X host=!ganymede;type=nfs;rhost=ganymede \
- X host=ganymede;type=ufs;dev=/dev/xy0h
- Xsysdiag type=link;fs=/usr/diag/sysdiag
- Xgames type=link;fs=/usr/games
- Xsjv -opts=rw,grpid,nosuid;rfs=/home/ganymede;sublink=sjv \
- X host=!ganymede;type=nfs;rhost=ganymede \
- X host=ganymede;type=ufs;dev=/dev/xy0h
- Xll1 -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/ll1 \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xksa -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/ksa \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xjvp -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/jvp \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xbin type=link;fs=/bin
- Xsa -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=samson/sa \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xbt -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=samson/bt \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xwrdo -opts=rw,grpid,nosuid;rfs=/home/ganymede;sublink=wrdo \
- X host=!ganymede;type=nfs;rhost=ganymede \
- X host=ganymede;type=ufs;dev=/dev/xy0h
- Xthp -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=thp \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xsys type=link;fs=/
- Xssp -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/ssp \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xsph -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=ai/sph \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xpah -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=jim/pah \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xnjw -opts=rw,grpid,nosuid;rfs=/home/dylan/dk2;sublink=njw \
- X host=!dylan;type=nfs;rhost=dylan \
- X host=dylan;type=ufs;dev=/dev/dsk/2s0
- Xmwt -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=mwt \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xmjh -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/mjh \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xkpt -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/kpt \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xfcs -opts=rw,grpid,nosuid;rfs=/home/ganymede;sublink=fcs \
- X host=!ganymede;type=nfs;rhost=ganymede \
- X host=ganymede;type=ufs;dev=/dev/xy0h
- Xdwj -opts=rw,grpid,nosuid;rfs=/home/achilles;sublink=dwj \
- X host=!achilles;type=nfs;rhost=achilles \
- X host=achilles;type=ufs;dev=/dev/xd0g
- Xhd -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=others/hd \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- Xcw -opts=rw,grpid,nosuid;rfs=/home/toytown;sublink=genesis/cw \
- X host=!toytown;type=nfs;rhost=toytown \
- X host=toytown;type=ufs;dev=/dev/xy1g
- END_OF_FILE
- if test 12180 -ne `wc -c <'examples/amd.homes'`; then
- echo shar: \"'examples/amd.homes'\" unpacked with wrong size!
- fi
- # end of 'examples/amd.homes'
- fi
- if test -f 'mtab.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mtab.c'\"
- else
- echo shar: Extracting \"'mtab.c'\" \(12010 characters\)
- sed "s/^X//" >'mtab.c' <<'END_OF_FILE'
- X/*
- X * $Id: mtab.c,v 5.1.1.3 90/01/11 17:11:26 jsp Exp Locker: jsp $
- X *
- X * Copyright (c) 1989 Jan-Simon Pendry
- X * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
- X * Copyright (c) 1989 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * This code is derived from software contributed to Berkeley by
- X * Jan-Simon Pendry at Imperial College, London.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by Imperial College of Science, Technology and Medicine, London, UK.
- X * The names of the College and University may not be used to endorse
- X * or promote products derived from this software without specific
- X * prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * %W% (Berkeley) %G%
- X */
- X
- X#include "am.h"
- X
- X/*
- X * Firewall /etc/mtab entries
- X */
- X#define MTAB_STRIPNL
- X
- X/*
- X * Do strict /etc/mtab locking
- X */
- X#define MTAB_LOCKING
- X
- X#ifdef READ_MTAB_FROM_FILE
- X#ifdef USE_FCNTL
- X#include <fcntl.h>
- X#else
- X#include <sys/file.h>
- X#endif
- X#endif
- X
- X#ifdef READ_MTAB_ULTRIX_STYLE
- X#include <sys/mount.h>
- X#include <sys/fs_types.h>
- X#endif
- X
- X#ifdef READ_MTAB_BSD_STYLE
- X#include <sys/mount.h>
- X#endif
- X
- X#ifdef UPDATE_MTAB
- X#include <sys/stat.h>
- Xstatic FILE *mnt_file;
- X
- X/*
- X * If the system is being trashed by something, then
- X * opening mtab may fail with ENFILE. So, go to sleep
- X * for a second and try again. (Yes - this has happened to me.)
- X *
- X * Note that this *may* block the automounter, oh well.
- X * If we get to this state then things are badly wrong anyway...
- X *
- X * Give the system 10 seconds to recover but then give up.
- X * Hopefully something else will exit and free up some file
- X * table slots in that time.
- X */
- X#define NFILE_RETRIES 10 /* seconds */
- X
- X#endif /* UPDATE_MTAB */
- X
- X#ifdef MTAB_LOCKING
- X#ifdef LOCK_FCNTL
- Xstatic int lock(fd)
- X{
- X int rc;
- X struct flock lk;
- X
- X lk.l_type = F_WRLCK;
- X lk.l_whence = 0;
- X lk.l_start = 0;
- X lk.l_len = 0;
- X
- Xagain:
- X rc = fcntl(fd, F_SETLKW, (caddr_t) &lk);
- X if (rc < 0 && (errno == EACCES || errno == EAGAIN)) {
- X#ifdef DEBUG
- X dlog("Blocked, trying to obtain exclusive mtab lock");
- X#endif
- X sleep(1);
- X goto again;
- X }
- X return rc;
- X}
- X#else
- X#define lock(fd) (flock((fd), LOCK_EX))
- X#endif
- X#endif /* MTAB_LOCKING */
- X
- X#ifdef MTAB_STRIPNL
- Xstatic void mtab_stripnl(s)
- Xchar *s;
- X{
- X do {
- X s = strchr(s, '\n');
- X if (s)
- X *s++ = ' ';
- X } while (s);
- X}
- X#endif
- X
- Xstatic struct mntent *mnt_dup(mp)
- X#ifdef READ_MTAB_BSD_STYLE
- Xstruct statfs *mp;
- X#endif
- X#ifdef READ_MTAB_ULTRIX_STYLE
- Xstruct fs_data *mp;
- X#endif
- X#ifdef READ_MTAB_FROM_FILE
- Xstruct mntent *mp;
- X#endif
- X{
- X struct mntent *new_mp = ALLOC(mntent);
- X#ifdef READ_MTAB_BSD_STYLE
- X char *ty;
- X new_mp->mnt_fsname = strdup(mp->f_mntfromname);
- X new_mp->mnt_dir = strdup(mp->f_mntonname);
- X switch (mp->f_type) {
- X case MOUNT_UFS: ty = MTAB_TYPE_UFS; break;
- X case MOUNT_NFS: ty = MTAB_TYPE_NFS; break;
- X case MOUNT_MFS: ty = MTAB_TYPE_MFS; break;
- X default: ty = "unknown"; break;
- X }
- X new_mp->mnt_type = strdup(ty);
- X new_mp->mnt_opts = strdup("unset");
- X new_mp->mnt_freq = 0;
- X new_mp->mnt_passno = 0;
- X#endif
- X
- X#ifdef READ_MTAB_ULTRIX_STYLE
- X new_mp->mnt_fsname = strdup(mp->fd_devname);
- X new_mp->mnt_dir = strdup(mp->fd_path);
- X if (mp->fd_fstype >= GT_NUMTYPES)
- X mp->fd_fstype = GT_UNKWN;
- X else if (gt_names[mp->fd_fstype] == 0)
- X mp->fd_fstype = GT_UNKWN;
- X new_mp->mnt_type = strdup(gt_names[mp->fd_fstype]);
- X new_mp->mnt_opts = strdup("unset");
- X
- X new_mp->mnt_freq = 0;
- X new_mp->mnt_passno = mp->fd_dev;
- X#endif
- X
- X#ifdef READ_MTAB_FROM_FILE
- X new_mp->mnt_fsname = strdup(mp->mnt_fsname);
- X new_mp->mnt_dir = strdup(mp->mnt_dir);
- X new_mp->mnt_type = strdup(mp->mnt_type);
- X new_mp->mnt_opts = strdup(mp->mnt_opts);
- X
- X new_mp->mnt_freq = mp->mnt_freq;
- X new_mp->mnt_passno = mp->mnt_passno;
- X#endif
- X return new_mp;
- X}
- X
- Xvoid mnt_free(mp)
- Xstruct mntent *mp;
- X{
- X free(mp->mnt_fsname);
- X free(mp->mnt_dir);
- X free(mp->mnt_type);
- X free(mp->mnt_opts);
- X free((voidp) mp);
- X}
- X
- X/*
- X * Read a mount table into memory
- X */
- X
- X#ifdef READ_MTAB_BSD_STYLE
- Xmntlist *read_mtab(fs)
- Xchar *fs;
- X{
- X mntlist **mpp, *mhp;
- X struct statfs *mntbufp, *mntp;
- X
- X int nloc = getmntinfo(&mntbufp);
- X
- X if (nloc == 0) {
- X plog(XLOG_ERROR, "Can't read mount table");
- X return 0;
- X }
- X
- X mpp = &mhp;
- X for (mntp = mntbufp; mntp < mntbufp + nloc; mntp++) {
- X /*
- X * Allocate a new slot
- X */
- X *mpp = ALLOC(mntlist);
- X
- X /*
- X * Copy the data returned by getmntent
- X */
- X (*mpp)->mnt = mnt_dup(mntp);
- X
- X /*
- X * Move to next pointer
- X */
- X mpp = &(*mpp)->mnext;
- X }
- X
- X return mhp;
- X}
- X#endif /* READ_MTAB_BSD_STYLE */
- X
- X#ifdef READ_MTAB_ULTRIX_STYLE
- Xmntlist *read_mtab(fs)
- Xchar *fs;
- X{
- X mntlist **mpp, *mhp;
- X
- X/* From: Piete Brooks <pb@cl.cam.ac.uk> */
- X
- X int loc=0;
- X#undef NMOUNT
- X#define NMOUNT 20
- X struct fs_data mountbuffer[NMOUNT], *fs_data;
- X int ret;
- X
- X mpp = &mhp;
- X while ((ret = getmountent(&loc, mountbuffer, NMOUNT)) > 0) {
- X for (fs_data = mountbuffer; fs_data < &mountbuffer[ret]; fs_data++) {
- X /*
- X * Allocate a new slot
- X */
- X *mpp = ALLOC(mntlist);
- X
- X /*
- X * Copy the data returned by getmntent
- X */
- X (*mpp)->mnt = mnt_dup(fs_data);
- X
- X /*
- X * Move to next pointer
- X */
- X mpp = &(*mpp)->mnext;
- X }
- X }
- X if (ret < 0) {
- X plog(XLOG_ERROR, "getmountent: %m");
- X return 0;
- X }
- X *mpp = 0;
- X
- X return mhp;
- X}
- X#endif /* READ_MTAB_ULTRIX_STYLE */
- X
- X#ifdef READ_MTAB_FROM_FILE
- Xmntlist *read_mtab(fs)
- Xchar *fs;
- X{
- X mntlist **mpp, *mhp;
- X
- X struct mntent *mep;
- X FILE *mfp = 0;
- X
- X#ifdef UPDATE_MTAB
- X /*
- X * There is a possible race condition if two processes enter
- X * this routine at the same time. One will be blocked by the
- X * exclusive lock below (or by the shared lock in setmntent)
- X * and by the time the second process has the exclusive lock
- X * it will be on the wrong underlying object. To check for this
- X * the mtab file is stat'ed before and after all the locking
- X * sequence, and if it is a different file then we assume that
- X * it may be the wrong file (only "may", since there is another
- X * race between the initial stat and the setmntent).
- X *
- X * Simpler solutions to this problem are invited...
- X */
- X int racing = 0;
- X#ifdef MTAB_LOCKING
- X int rc;
- X int retries = 0;
- X struct stat st_before, st_after;
- X#endif /* MTAB_LOCKING */
- X
- X if (mnt_file) {
- X#ifdef DEBUG
- X dlog("Forced close on %s in read_mtab", mtab);
- X#endif /* DEBUG */
- X endmntent(mnt_file);
- X mnt_file = 0;
- X }
- X
- X#ifdef MTAB_LOCKING
- Xagain:
- X if (mfp) {
- X endmntent(mfp);
- X mfp = 0;
- X }
- X
- X clock_valid = 0;
- X if (stat(mtab, &st_before) < 0) {
- X plog(XLOG_ERROR, "%s: stat: %m", mtab);
- X if (errno == ESTALE) {
- X /* happens occasionally */
- X sleep(1);
- X goto again;
- X }
- X return 0;
- X }
- X#endif /* MTAB_LOCKING */
- X#endif /* UPDATE_MTAB */
- X
- Xeacces:
- X mfp = setmntent(mtab, "r+");
- X if (!mfp) {
- X /*
- X * Since setmntent locks the descriptor, it
- X * is possible it can fail... so retry if
- X * needed.
- X */
- X if (errno == EACCES || errno == EAGAIN) {
- X#ifdef DEBUG
- X dlog("Blocked, trying to obtain exclusive mtab lock");
- X#endif /* DEBUG */
- X goto eacces;
- X } else if (errno == ENFILE && retries++ < NFILE_RETRIES) {
- X sleep(1);
- X goto eacces;
- X }
- X
- X plog(XLOG_ERROR, "setmntent(\"%s\", \"r+\"): %m", mtab);
- X return 0;
- X }
- X
- X#ifdef MTAB_LOCKING
- X#ifdef UPDATE_MTAB
- X /*
- X * At this point we have an exclusive lock on the mount list,
- X * but it may be the wrong one so...
- X */
- X
- X /*
- X * Need to get an exclusive lock on the current
- X * mount table until we have a new copy written
- X * out, when the lock is released in free_mntlist.
- X * flock is good enough since the mount table is
- X * not shared between machines.
- X */
- X do
- X rc = lock(fileno(mfp));
- X while (rc < 0 && errno == EINTR);
- X if (rc < 0) {
- X plog(XLOG_ERROR, "Couldn't lock %s: %m", mtab);
- X endmntent(mfp);
- X return 0;
- X }
- X /*
- X * Now check whether the mtab file has changed under our feet
- X */
- X if (stat(mtab, &st_after) < 0) {
- X plog(XLOG_ERROR, "%s: stat", mtab);
- X goto again;
- X }
- X
- X if (st_before.st_dev != st_after.st_dev ||
- X st_before.st_ino != st_after.st_ino) {
- X if (racing == 0) {
- X /* Sometimes print a warning */
- X plog(XLOG_WARNING,
- X "Possible mount table race - retrying %s", fs);
- X }
- X racing = (racing+1) & 3;
- X goto again;
- X }
- X#endif /* UPDATE_MTAB */
- X#endif /* MTAB_LOCKING */
- X
- X mpp = &mhp;
- X
- X/*
- X * XXX - In SunOS 4 there is (yet another) memory leak
- X * which loses 1K the first time getmntent is called.
- X * (jsp)
- X */
- X while (mep = getmntent(mfp)) {
- X /*
- X * Allocate a new slot
- X */
- X *mpp = ALLOC(mntlist);
- X
- X /*
- X * Copy the data returned by getmntent
- X */
- X (*mpp)->mnt = mnt_dup(mep);
- X
- X /*
- X * Move to next pointer
- X */
- X mpp = &(*mpp)->mnext;
- X }
- X *mpp = 0;
- X
- X#ifdef UPDATE_MTAB
- X /*
- X * If we are not updating the mount table then we
- X * can free the resources held here, otherwise they
- X * must be held until the mount table update is complete
- X */
- X mnt_file = mfp;
- X#else
- X endmntent(mfp);
- X#endif /* UPDATE_MTAB */
- X
- X return mhp;
- X}
- X#endif /* READ_MTAB_FROM_FILE */
- X
- X/*
- X * Throw away a mount list
- X */
- Xvoid free_mntlist(mp)
- Xmntlist *mp;
- X{
- X mntlist *mp2;
- X
- X while (mp2 = mp) {
- X mp = mp->mnext;
- X if (mp2->mnt)
- X mnt_free(mp2->mnt);
- X free(mp2);
- X }
- X
- X#ifdef UPDATE_MTAB
- X /*
- X * Release file lock, by closing the file
- X */
- X if (mnt_file) {
- X endmntent(mnt_file);
- X mnt_file = 0;
- X }
- X#endif /* UPDATE_MTAB */
- X}
- X
- X#ifdef UPDATE_MTAB
- X/*
- X * Write out a mount list
- X */
- Xvoid rewrite_mtab(mp)
- Xmntlist *mp;
- X{
- X FILE *mfp;
- X
- X /*
- X * Concoct a temporary name in the same
- X * directory as the target mount table
- X * so that rename() will work.
- X */
- X char tmpname[64];
- X int retries;
- X int tmpfd;
- X char *cp;
- X char *mcp = mtab;
- X cp = strrchr(mcp, '/');
- X if (cp) {
- X bcopy(mcp, tmpname, cp - mcp);
- X tmpname[cp-mcp] = '\0';
- X } else {
- X plog(XLOG_WARNING, "No '/' in mtab (%s), using \".\" as tmp directory", mtab);
- X tmpname[0] = '.'; tmpname[1] = '\0';
- X }
- X strcat(tmpname, "/mtabXXXXXX");
- X mktemp(tmpname);
- X retries = 0;
- Xenfile1:
- X if ((tmpfd = open(tmpname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
- X if (errno == ENFILE && retries++ < NFILE_RETRIES) {
- X sleep(1);
- X goto enfile1;
- X }
- X plog(XLOG_ERROR, "%s: open: %m", tmpname);
- X return;
- X }
- X if (close(tmpfd) < 0)
- X plog(XLOG_ERROR, "Couldn't close tmp file descriptor: %m");
- X
- X retries = 0;
- Xenfile2:
- X mfp = setmntent(tmpname, "w");
- X if (!mfp) {
- X if (errno == ENFILE && retries++ < NFILE_RETRIES) {
- X sleep(1);
- X goto enfile2;
- X }
- X plog(XLOG_ERROR, "setmntent(\"%s\", \"w\"): %m", tmpname);
- X return;
- X }
- X
- X while (mp) {
- X if (mp->mnt)
- X if (addmntent(mfp, mp->mnt))
- X plog(XLOG_ERROR, "Can't write entry to %s", tmpname);
- X mp = mp->mnext;
- X }
- X
- X endmntent(mfp);
- X
- X /*
- X * Rename temporary mtab to real mtab
- X */
- X if (rename(tmpname, mtab) < 0)
- X plog(XLOG_ERROR, "rename %s to %s: %m", tmpname, mtab);
- X}
- X
- X/*
- X * Append a mntent structure to the
- X * current mount table.
- X */
- Xvoid write_mntent(mp)
- Xstruct mntent *mp;
- X{
- X int retries = 0;
- X FILE *mfp;
- Xenfile:
- X mfp = setmntent(mtab, "a");
- X if (mfp) {
- X#ifdef MTAB_STRIPNL
- X mtab_stripnl(mp->mnt_opts);
- X#endif /* MTAB_STRIPNL */
- X if (addmntent(mfp, mp))
- X plog(XLOG_ERROR, "Couldn't write %s: %m", mtab);
- X endmntent(mfp);
- X } else {
- X if (errno == ENFILE && retries < NFILE_RETRIES) {
- X sleep(1);
- X goto enfile;
- X }
- X plog(XLOG_ERROR, "setmntent(\"%s\", \"a\"): %m", mtab);
- X }
- X}
- X#endif /* UPDATE_MTAB */
- X
- X/*
- X * Utility routine which determines the value of a
- X * numeric option in the mount options (such as port=%d).
- X * Returns 0 if the option is not specified.
- X */
- Xint hasmntval(mnt, opt)
- Xstruct mntent *mnt;
- Xchar *opt;
- X{
- X char *str = hasmntopt(mnt, opt);
- X if (str) {
- X char *eq = strchr(str, '=');
- X if (eq)
- X return atoi(eq+1);
- X else
- X plog(XLOG_USER, "bad numeric option \"%s\" in \"%s\"", opt, str);
- X }
- X
- X return 0;
- X}
- END_OF_FILE
- if test 12010 -ne `wc -c <'mtab.c'`; then
- echo shar: \"'mtab.c'\" unpacked with wrong size!
- fi
- # end of 'mtab.c'
- fi
- if test -f 'opts.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'opts.c'\"
- else
- echo shar: Extracting \"'opts.c'\" \(14812 characters\)
- sed "s/^X//" >'opts.c' <<'END_OF_FILE'
- X/*
- X * $Id: opts.c,v 5.1 89/11/17 18:21:43 jsp Exp Locker: jsp $
- X *
- X * Copyright (c) 1989 Jan-Simon Pendry
- X * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
- X * Copyright (c) 1989 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * This code is derived from software contributed to Berkeley by
- X * Jan-Simon Pendry at Imperial College, London.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by Imperial College of Science, Technology and Medicine, London, UK.
- X * The names of the College and University may not be used to endorse
- X * or promote products derived from this software without specific
- X * prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * %W% (Berkeley) %G%
- X */
- X
- X#include "am.h"
- X
- Xextern char *getenv P((char *));
- X
- X/*
- X * static copy of the options with
- X * which to play
- X */
- Xstatic struct am_opts fs_static;
- X
- Xstatic char *opt_host = hostname;
- Xstatic char *opt_hostd = hostd;
- Xstatic char nullstr[] = "";
- Xstatic char *opt_key = nullstr;
- Xstatic char *opt_map = nullstr;
- Xstatic char *opt_path = nullstr;
- X
- X/*
- X * Length of longest option name
- X */
- X#define NLEN 16
- X#define S(x) (x) , (sizeof(x)-1)
- Xstatic struct opt {
- X char *name; /* Name of the option */
- X int nlen; /* Length of option name */
- X char **optp; /* Pointer to option value string */
- X char **sel_p; /* Pointer to selector value string */
- X} opt_fields[] = {
- X /* Options in something corresponding to frequency of use */
- X { S("opts"), &fs_static.opt_opts, 0 },
- X { S("host"), 0, &opt_host },
- X { S("hostd"), 0, &opt_hostd },
- X { S("type"), &fs_static.opt_type, 0 },
- X { S("rhost"), &fs_static.opt_rhost, 0 },
- X { S("rfs"), &fs_static.opt_rfs, 0 },
- X { S("fs"), &fs_static.opt_fs, 0 },
- X { S("key"), 0, &opt_key },
- X { S("map"), 0, &opt_map },
- X { S("sublink"), &fs_static.opt_sublink, 0 },
- X { S("arch"), 0, &arch },
- X { S("dev"), &fs_static.opt_dev, 0 },
- X { S("pref"), &fs_static.opt_pref, 0 },
- X { S("path"), 0, &opt_path },
- X { S("autodir"), 0, &auto_dir },
- X { S("delay"), &fs_static.opt_delay, 0 },
- X { S("domain"), 0, &hostdomain },
- X { S("karch"), 0, &karch },
- X { S("cluster"), 0, &cluster },
- X { S("byte"), 0, &endian },
- X { S("os"), 0, &op_sys },
- X { S("mount"), &fs_static.opt_mount, 0 },
- X { S("unmount"), &fs_static.opt_unmount, 0 },
- X { S("cache"), &fs_static.opt_cache, 0 },
- X { S("user"), &fs_static.opt_user, 0 },
- X { S("group"), &fs_static.opt_group, 0 },
- X { 0, 0, 0, 0 },
- X};
- X
- Xtypedef struct opt_apply opt_apply;
- Xstruct opt_apply {
- X char **opt;
- X char *val;
- X};
- X
- X/*
- X * Specially expand the remote host name first
- X */
- Xstatic opt_apply rhost_expansion[] = {
- X { &fs_static.opt_rhost, "${host}" },
- X { 0, 0 },
- X};
- X/*
- X * List of options which need to be expanded
- X * Note that this the order here _may_ be important.
- X */
- Xstatic opt_apply expansions[] = {
- X/* { &fs_static.opt_dir, 0 }, */
- X { &fs_static.opt_sublink, 0 },
- X { &fs_static.opt_rfs, "${path}" },
- X { &fs_static.opt_fs, "${autodir}/${rhost}${rfs}" },
- X { &fs_static.opt_opts, "rw" },
- X { &fs_static.opt_mount, 0 },
- X { &fs_static.opt_unmount, 0 },
- X { 0, 0 },
- X};
- X
- X/*
- X * List of options which need to be free'ed before re-use
- X */
- Xstatic opt_apply to_free[] = {
- X { &fs_static.fs_glob, 0 },
- X { &fs_static.fs_local, 0 },
- X { &fs_static.fs_mtab, 0 },
- X/* { &fs_static.opt_dir, 0 }, */
- X { &fs_static.opt_sublink, 0 },
- X { &fs_static.opt_rfs, 0 },
- X { &fs_static.opt_fs, 0 },
- X { &fs_static.opt_rhost, 0 },
- X { &fs_static.opt_opts, 0 },
- X { &fs_static.opt_mount, 0 },
- X { &fs_static.opt_unmount, 0 },
- X { 0, 0 },
- X};
- X
- X/*
- X * Skip to next option in the string
- X */
- Xstatic char *opt P((char**));
- Xstatic char *opt(p)
- Xchar **p;
- X{
- X char *cp = *p;
- X char *dp = cp;
- X char *s = cp;
- X
- Xtop:
- X while (*cp && *cp != ';') {
- X if (*cp == '\"') {
- X /*
- X * Skip past string
- X */
- X cp++;
- X while (*cp && *cp != '\"')
- X *dp++ = *cp++;
- X if (*cp)
- X cp++;
- X } else {
- X *dp++ = *cp++;
- X }
- X }
- X
- X /*
- X * Skip past any remaining ';'s
- X */
- X while (*cp == ';')
- X cp++;
- X
- X /*
- X * If we have a zero length string
- X * and there are more fields, then
- X * parse the next one. This allows
- X * sequences of empty fields.
- X */
- X if (*cp && dp == s)
- X goto top;
- X
- X *dp = '\0';
- X
- X *p = cp;
- X return s;
- X}
- X
- Xstatic int eval_opts P((char*));
- Xstatic int eval_opts(opts)
- Xchar *opts;
- X{
- X /*
- X * Fill in the global structure fs_static by
- X * cracking the string opts. opts may be
- X * scribbled on at will.
- X */
- X char *o = opts;
- X char *f;
- X
- X /*
- X * For each user-specified option
- X */
- X while (*(f = opt(&o))) {
- X struct opt *op;
- X enum vs_opt { OldSyn, SelEQ, SelNE, VarAss } vs_opt;
- X char *eq = strchr(f, '=');
- X char *opt;
- X if (!eq || eq[1] == '\0' || eq == f) {
- X /*
- X * No value, just continue
- X */
- X plog(XLOG_USER, "No value component in \"%s\"", f);
- X continue;
- X }
- X
- X /*
- X * Check what type of operation is happening
- X * !=, =! is SelNE
- X * == is SelEQ
- X * := is VarAss
- X * = is OldSyn (either SelEQ or VarAss)
- X */
- X if (eq[-1] == '!') { /* != */
- X vs_opt = SelNE;
- X eq[-1] = '\0';
- X opt = eq + 1;
- X } else if (eq[-1] == ':') { /* := */
- X vs_opt = VarAss;
- X eq[-1] = '\0';
- X opt = eq + 1;
- X } else if (eq[1] == '=') { /* == */
- X vs_opt = SelEQ;
- X eq[0] = '\0';
- X opt = eq + 2;
- X } else if (eq[1] == '!') { /* =! */
- X vs_opt = SelNE;
- X eq[0] = '\0';
- X opt = eq + 2;
- X } else { /* = */
- X vs_opt = OldSyn;
- X eq[0] = '\0';
- X opt = eq + 1;
- X }
- X
- X /*
- X * For each recognised option
- X */
- X for (op = opt_fields; op->name; op++) {
- X /*
- X * Check whether they match
- X */
- X if (FSTREQ(op->name, f)) {
- X switch (vs_opt) {
- X#if AMD_COMPAT <= 5000108
- X case OldSyn:
- X if (!op->sel_p) {
- X *op->optp = opt;
- X break;
- X }
- X /* fall through ... */
- X#endif /* 5000108 */
- X case SelEQ:
- X case SelNE:
- X if (op->sel_p && (STREQ(*op->sel_p, opt) == (vs_opt == SelNE))) {
- X plog(XLOG_MAP, "map selector %s (=%s) did not %smatch %s",
- X op->name,
- X *op->sel_p,
- X vs_opt == SelNE ? "not " : "",
- X opt);
- X return 0;
- X }
- X break;
- X
- X case VarAss:
- X if (op->sel_p) {
- X plog(XLOG_USER, "Can't assign to a selector (%s)", op->name);
- X return 0;
- X }
- X *op->optp = opt;
- X break;
- X }
- X break;
- X }
- X }
- X
- X if (!op->name)
- X plog(XLOG_USER, "Unrecognised key \"%s\"", f);
- X }
- X
- X return 1;
- X}
- X
- X/*
- X * Free an option
- X */
- Xstatic void free_op P((opt_apply*, int));
- X/*ARGSUSED*/
- Xstatic void free_op(p, b)
- Xopt_apply *p;
- Xint b;
- X{
- X if (*p->opt) {
- X free(*p->opt);
- X *p->opt = 0;
- X }
- X}
- X
- X/*
- X * Macro-expand an option. Note that this does not
- X * handle recursive expansions. They will go badly wrong.
- X * If sel is true then old expand selectors, otherwise
- X * don't expand selectors.
- X */
- Xstatic void expand_op P((opt_apply*, int));
- Xstatic void expand_op(p, sel_p)
- Xopt_apply *p;
- Xint sel_p;
- X{
- X/*
- X * The BUFSPACE macros checks that there is enough space
- X * left in the expansion buffer. If there isn't then we
- X * give up completely. This is done to avoid crashing the
- X * automounter itself (which would be a bad thing to do).
- X */
- X#define BUFSPACE(ep, len) (((ep) + (len)) < expbuf+MAXPATHLEN)
- Xstatic char expand_error[] = "No space to expand \"%s\"";
- X
- X char expbuf[MAXPATHLEN];
- X char nbuf[NLEN+1];
- X char *ep = expbuf;
- X char *cp = *p->opt;
- X char *dp;
- X#ifdef DEBUG
- X char *cp_orig = *p->opt;
- X#endif
- X struct opt *op;
- X
- X while (dp = strchr(cp, '$')) {
- X char ch;
- X /*
- X * First copy up to the $
- X */
- X { int len = dp - cp;
- X if (BUFSPACE(ep, len)) {
- X strncpy(ep, cp, len);
- X ep += len;
- X } else {
- X plog(XLOG_ERROR, expand_error, *p->opt);
- X goto out;
- X }
- X }
- X cp = dp + 1;
- X ch = *cp++;
- X if (ch == '$') {
- X if (BUFSPACE(ep, 1)) {
- X *ep++ = '$';
- X } else {
- X plog(XLOG_ERROR, expand_error, *p->opt);
- X goto out;
- X }
- X } else if (ch == '{') {
- X /* Expansion... */
- X enum { E_All, E_Dir, E_File } todo;
- X /*
- X * Find closing brace
- X */
- X char *br_p = strchr(cp, '}');
- X int len;
- X /*
- X * Check we found it
- X */
- X if (!br_p) {
- X /*
- X * Just give up
- X */
- X plog(XLOG_USER, "No closing '}' in \"%s\"", *p->opt);
- X goto out;
- X }
- X len = br_p - cp;
- X /*
- X * Figure out which part of the variable to grab.
- X */
- X if (*cp == '/') {
- X /*
- X * Just take the last component
- X */
- X todo = E_File;
- X cp++;
- X --len;
- X } else if (br_p[-1] == '/') {
- X /*
- X * Take all but the last component
- X */
- X todo = E_Dir;
- X --len;
- X } else {
- X /*
- X * Take the whole lot
- X */
- X todo = E_All;
- X }
- X /*
- X * Truncate if too long. Since it won't
- X * match anyway it doesn't matter that
- X * it has been cut short.
- X */
- X if (len > NLEN)
- X len = NLEN;
- X /*
- X * Put the string into another buffer so
- X * we can do comparisons.
- X */
- X strncpy(nbuf, cp, len);
- X nbuf[len] = '\0';
- X /*
- X * Advance cp
- X */
- X cp = br_p + 1;
- X /*
- X * Search the option array
- X */
- X for (op = opt_fields; op->name; op++) {
- X /*
- X * Check for match
- X */
- X if (len == op->nlen && STREQ(op->name, nbuf)) {
- X char xbuf[NLEN+3];
- X char *val;
- X /*
- X * Found expansion. Copy
- X * the correct value field.
- X */
- X if (!(!op->sel_p == !sel_p)) {
- X /*
- X * Copy the string across unexpanded
- X */
- X sprintf(xbuf, "${%s%s%s}",
- X todo == E_File ? "/" : "",
- X nbuf,
- X todo == E_Dir ? "/" : "");
- X val = xbuf;
- X } else if (op->sel_p) {
- X val = *op->sel_p;
- X } else {
- X val = *op->optp;
- X }
- X if (val) {
- X /*
- X * Do expansion:
- X * ${/var} means take just the last part
- X * ${var/} means take all but the last part
- X * ${var} means take the whole lot
- X */
- X int vlen = strlen(val);
- X char *vptr = val;
- X switch (todo) {
- X case E_Dir:
- X vptr = strchr(val, '/');
- X if (vptr)
- X vlen = vptr - val;
- X vptr = val;
- X break;
- X case E_File:
- X vptr = strchr(val, '/');
- X if (vptr) {
- X vptr++;
- X vlen = strlen(vptr);
- X }
- X break;
- X }
- X#ifdef DEBUG
- X /*dlog("Expanding \"%s\" to \"%s\"", nbuf, val);*/
- X#endif
- X if (BUFSPACE(ep, vlen)) {
- X strcpy(ep, vptr);
- X ep += vlen;
- X } else {
- X plog(XLOG_ERROR, expand_error, *p->opt);
- X goto out;
- X }
- X }
- X /*
- X * Done with this variable
- X */
- X break;
- X }
- X }
- X /*
- X * Check that the search was succesful
- X */
- X if (!op->name) {
- X /*
- X * If it wasn't then scan the
- X * environment for that name
- X * and use any value found
- X */
- X char *env = getenv(nbuf);
- X if (env) {
- X int vlen = strlen(env);
- X
- X if (BUFSPACE(ep, vlen)) {
- X strcpy(ep, env);
- X ep += vlen;
- X } else {
- X plog(XLOG_ERROR, expand_error, *p->opt);
- X goto out;
- X }
- X#ifdef DEBUG
- X Debug(D_STR)
- X plog(XLOG_DEBUG, "Environment gave \"%s\" -> \"%s\"", nbuf, env);
- X#endif
- X } else {
- X plog(XLOG_USER, "Unknown sequence \"${%s}\"", nbuf);
- X }
- X }
- X } else {
- X /*
- X * Error, error
- X */
- X plog(XLOG_USER, "Unknown $ sequence in \"%s\"", *p->opt);
- X }
- X }
- X
- Xout:
- X /*
- X * Handle common case - no expansion
- X */
- X if (cp == *p->opt) {
- X *p->opt = strdup(cp);
- X } else {
- X /*
- X * Finish off the expansion
- X */
- X if (BUFSPACE(ep, strlen(cp))) {
- X strcpy(ep, cp);
- X /*ep += strlen(ep);*/
- X } else {
- X plog(XLOG_ERROR, expand_error, *p->opt);
- X }
- X
- X /*
- X * Save the exansion
- X */
- X *p->opt = strdup(expbuf);
- X }
- X
- X /*
- X * Normalize slashes in the string.
- X */
- X { char *f = strchr(*p->opt, '/');
- X if (f) {
- X char *t = f;
- X do {
- X /* assert(*f == '/'); */
- X /* copy a single / across */
- X *t++ = *f++;
- X
- X /* assert(f[-1] == '/'); */
- X /* skip past more /'s */
- X while (*f == '/')
- X f++;
- X
- X /* assert(*f != '/'); */
- X /* keep copying up to next / */
- X do {
- X *t++ = *f++;
- X } while (*f && *f != '/');
- X
- X /* assert(*f == 0 || *f == '/'); */
- X
- X } while (*f);
- X }
- X }
- X
- X#ifdef DEBUG
- X Debug(D_STR) {
- X plog(XLOG_DEBUG, "Expansion of \"%s\"...", cp_orig);
- X plog(XLOG_DEBUG, "... is \"%s\"", *p->opt);
- X }
- X#endif
- X}
- X
- X/*
- X * Wrapper for expand_op
- X */
- Xstatic void expand_opts P((opt_apply*, int));
- Xstatic void expand_opts(p, sel_p)
- Xopt_apply *p;
- Xint sel_p;
- X{
- X if (*p->opt) {
- X expand_op(p, sel_p);
- X } else if (p->val) {
- X /*
- X * Do double expansion, remembering
- X * to free the string from the first
- X * expansion...
- X */
- X char *s = *p->opt = expand_key(p->val);
- X expand_op(p, sel_p);
- X free(s);
- X }
- X}
- X
- X/*
- X * Apply a function to a list of options
- X */
- Xstatic void apply_opts(op, ppp, b)
- Xvoid (*op)();
- Xopt_apply ppp[];
- Xint b;
- X{
- X opt_apply *pp;
- X for (pp = ppp; pp->opt; pp++)
- X (*op)(pp, b);
- X}
- X
- X/*
- X * Free the option table
- X */
- Xvoid free_opts(fo)
- Xam_opts *fo;
- X{
- X /*
- X * Copy in the structure we are playing with
- X */
- X fs_static = *fo;
- X
- X /*
- X * Free previously allocated memory
- X */
- X apply_opts(free_op, to_free, FALSE);
- X}
- X
- X/*
- X * Expand lookup key
- X */
- Xchar *expand_key(key)
- Xchar *key;
- X{
- X opt_apply oa;
- X
- X oa.opt = &key; oa.val = 0;
- X expand_opts(&oa, TRUE);
- X
- X return key;
- X}
- X
- Xint eval_fs_opts(fo, opts, g_opts, path, key, map)
- Xam_opts *fo;
- Xchar *opts, *g_opts, *path, *key, *map;
- X{
- X int ok = TRUE;
- X
- X free_opts(fo);
- X
- X /*
- X * Clear out the option table
- X */
- X bzero((voidp) &fs_static, sizeof(fs_static));
- X bzero((voidp) fo, sizeof(*fo));
- X
- X /*
- X * Set key before expansion
- X */
- X opt_key = key;
- X opt_map = map;
- X opt_path = path;
- X
- X /*
- X * Expand global options
- X */
- X fs_static.fs_glob = expand_key(g_opts);
- X
- X /*
- X * Expand local options
- X */
- X fs_static.fs_local = expand_key(opts);
- X
- X /*
- X * Expand default (global) options
- X */
- X if (!eval_opts(fs_static.fs_glob))
- X ok = FALSE;
- X
- X /*
- X * Expand local options
- X */
- X if (ok && !eval_opts(fs_static.fs_local))
- X ok = FALSE;
- X
- X /*
- X * Normalise remote host name.
- X * 1. Expand variables
- X * 2. Normalize relative to host tables
- X * 3. Strip local domains from the remote host
- X * name before using it in other expansions.
- X * This makes mount point names and other things
- X * much shorter, while allowing cross domain
- X * sharing of mount maps.
- X */
- X apply_opts(expand_opts, rhost_expansion, FALSE);
- X if (ok && fs_static.opt_rhost && *fs_static.opt_rhost)
- X host_normalize(&fs_static.opt_rhost);
- X
- X /*
- X * Macro expand the options.
- X * Do this regardless of whether we are accepting
- X * this mount - otherwise nasty things happen
- X * with memory allocation.
- X */
- X apply_opts(expand_opts, expansions, FALSE);
- X
- X /*
- X * ok... copy the data back out.
- X */
- X *fo = fs_static;
- X
- X /*
- X * Clear defined options
- X */
- X opt_key = opt_map = opt_path = nullstr;
- X
- X return ok;
- X}
- END_OF_FILE
- if test 14812 -ne `wc -c <'opts.c'`; then
- echo shar: \"'opts.c'\" unpacked with wrong size!
- fi
- # end of 'opts.c'
- fi
- if test -f 'srvr_nfs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'srvr_nfs.c'\"
- else
- echo shar: Extracting \"'srvr_nfs.c'\" \(11929 characters\)
- sed "s/^X//" >'srvr_nfs.c' <<'END_OF_FILE'
- X/*
- X * $Id: srvr_nfs.c,v 5.1.1.2 90/01/11 17:21:08 jsp Exp Locker: jsp $
- X *
- X * Copyright (c) 1990 Jan-Simon Pendry
- X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
- X * Copyright (c) 1990 The Regents of the University of California.
- X * All rights reserved.
- X *
- X * This code is derived from software contributed to Berkeley by
- X * Jan-Simon Pendry at Imperial College, London.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by Imperial College of Science, Technology and Medicine, London, UK.
- X * The names of the College and University may not be used to endorse
- X * or promote products derived from this software without specific
- X * prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X *
- X * %W% (Berkeley) %G%
- X */
- X
- X/*
- X * NFS server modeling
- X */
- X
- X#include "am.h"
- X#include <netdb.h>
- X#include <rpc/pmap_prot.h>
- X#include "mount.h"
- X
- Xextern qelem nfs_srvr_list;
- Xqelem nfs_srvr_list = { &nfs_srvr_list, &nfs_srvr_list };
- X
- Xtypedef struct nfs_private {
- X u_short np_mountd; /* Mount daemon port number */
- X int np_ping; /* Number of failed ping attempts */
- X int np_xid; /* RPC transaction id for pings */
- X int np_error; /* Error during portmap request */
- X} nfs_private;
- X
- Xstatic int np_xid; /* For NFS pings */
- X#define NPXID_ALLOC() (++np_xid)
- X/*#define NPXID_ALLOC() ((++np_xid&0x0fffffff) == 0 ? npxid_gc() : np_xid)*/
- X
- X/*
- X * Number of pings allowed to fail before host is declared down
- X * - three-fifths of the allowed mount time...
- X */
- X#define MAX_ALLOWED_PINGS ((((ALLOWED_MOUNT_TIME + 5 * AM_PINGER - 1) * 3) / 5) / AM_PINGER)
- X/*
- X * How often to ping when starting a new server
- X */
- X#define FAST_NFS_PING 3
- X
- Xstatic int ping_len;
- Xstatic char ping_buf[sizeof(struct rpc_msg) + 32];
- X
- X/*
- X * Startup the NFS ping
- X */
- Xstatic void start_ping()
- X{
- X XDR ping_xdr;
- X struct rpc_msg ping_msg;
- X
- X rpc_msg_init(&ping_msg, NFS_PROGRAM, NFS_VERSION, NFSPROC_NULL);
- X
- X /*
- X * Create an XDR endpoint
- X */
- X xdrmem_create(&ping_xdr, ping_buf, sizeof(ping_buf), XDR_ENCODE);
- X
- X /*
- X * Create the NFS ping message
- X */
- X if (!xdr_callmsg(&ping_xdr, &ping_msg)) {
- X plog(XLOG_ERROR, "Couldn't create ping RPC message");
- X going_down(3);
- X }
- X
- X /*
- X * Find out how long it is
- X */
- X ping_len = xdr_getpos(&ping_xdr);
- X
- X /*
- X * Destroy the XDR endpoint - we don't need it anymore
- X */
- X xdr_destroy(&ping_xdr);
- X}
- X
- X
- X/*
- X * Called when a portmap reply arrives
- X */
- Xstatic void got_portmap(pkt, len, sa, ia, idv, done)
- Xvoidp pkt;
- Xint len;
- Xstruct sockaddr_in *sa, *ia;
- Xvoidp idv;
- Xint done;
- X{
- X fserver *fs2 = (fserver *) idv;
- X fserver *fs = 0;
- X ITER(fs, fserver, &nfs_srvr_list)
- X if (fs == fs2)
- X break;
- X
- X if (fs == fs2) {
- X u_long port = 0; /* XXX - should be short but protocol is naff */
- X int error = done ? pickup_rpc_reply(pkt, len, (voidp) &port, xdr_u_long) : -1;
- X nfs_private *np = (nfs_private *) fs->fs_private;
- X if (!error && port) {
- X#ifdef DEBUG
- X dlog("got port (%d) for mountd on %s", port, fs->fs_host);
- X#endif
- X /*
- X * Grab the port number. Portmap sends back
- X * an unsigned long in native ordering, so it
- X * needs converting to a unsigned short in
- X * network ordering.
- X */
- X np->np_mountd = htons((u_short) port);
- X np->np_error = 0;
- X } else {
- X#ifdef DEBUG
- X dlog("Error fetching port for mountd on %s", fs->fs_host);
- X#endif
- X /*
- X * Almost certainly no mountd running on remote host
- X */
- X np->np_error = error ? error : ETIMEDOUT;
- X }
- X if (fs->fs_flags & FSF_WANT)
- X wakeup_srvr(fs);
- X } else if (done) {
- X#ifdef DEBUG
- X dlog("Got portmap for old port request");
- X#endif
- X } else {
- X#ifdef DEBUG
- X dlog("portmap request timed out");
- X#endif
- X }
- X}
- X
- X/*
- X * Obtain portmap information
- X */
- Xstatic int call_portmap(fs, auth, prog, vers, prot)
- Xfserver *fs;
- XAUTH *auth;
- Xunsigned long prog, vers, prot;
- X{
- X struct rpc_msg pmap_msg;
- X int len;
- X char iobuf[UDPMSGSIZE];
- X int error;
- X struct pmap pmap;
- X
- X rpc_msg_init(&pmap_msg, PMAPPROG, PMAPVERS, (unsigned long) 0);
- X pmap.pm_prog = prog;
- X pmap.pm_vers = vers;
- X pmap.pm_prot = prot;
- X pmap.pm_port = 0;
- X len = make_rpc_packet(iobuf, sizeof(iobuf), PMAPPROC_GETPORT,
- X &pmap_msg, (voidp) &pmap, xdr_pmap, auth);
- X if (len > 0) {
- X struct sockaddr_in sin;
- X bzero((voidp) &sin, sizeof(sin));
- X sin = *fs->fs_ip;
- X sin.sin_port = htons(PMAPPORT);
- X error = fwd_packet(RPC_XID_PORTMAP, (voidp) iobuf, len,
- X &sin, &sin, (voidp) fs, got_portmap);
- X } else {
- X error = -len;
- X }
- X return error;
- X}
- X
- Xstatic void nfs_keepalive P((fserver*));
- X
- X/*
- X * This is called when we get a reply to an RPC ping.
- X * The value of id wass taken from the nfs_private
- X * structure when the ping was transmitted.
- X */
- X/*ARGSUSED*/
- Xstatic void nfs_pinged(pkt, len, sp, tsp, idv, done)
- Xvoidp pkt;
- Xint len;
- Xstruct sockaddr_in *sp, *tsp;
- Xvoidp idv;
- Xint done;
- X{
- X int xid = (int) idv;
- X fserver *fs;
- X int found_map = 0;
- X
- X if (!done)
- X return;
- X
- X /*
- X * For each node...
- X */
- X ITER(fs, fserver, &nfs_srvr_list) {
- X nfs_private *np = (nfs_private *) fs->fs_private;
- X if (np->np_xid == xid) {
- X /*
- X * Reset the ping counter.
- X * Update the keepalive timer.
- X * Log what happened.
- X */
- X if (fs->fs_flags & FSF_DOWN) {
- X fs->fs_flags &= ~FSF_DOWN;
- X if (fs->fs_flags & FSF_VALID) {
- X plog(XLOG_INFO, "file server %s type nfs is up", fs->fs_host);
- X } else {
- X plog(XLOG_INFO, "file server %s type nfs starts up", fs->fs_host);
- X fs->fs_flags |= FSF_VALID;
- X }
- X /*if (fs->fs_flags & FSF_WANT)
- X wakeup_srvr(fs);*/
- X } else {
- X#ifdef DEBUG
- X dlog("file server %s type nfs is still up", fs->fs_host);
- X#endif
- X }
- X
- X /*
- X * Speed up the pings again
- X */
- X if (np->np_ping >= MAX_ALLOWED_PINGS) {
- X untimeout(fs->fs_cid);
- X fs->fs_cid = timeout(fs->fs_pinger, nfs_keepalive, (voidp) fs);
- X }
- X
- X /*
- X * New RPC xid...
- X */
- X np->np_xid = NPXID_ALLOC();
- X
- X /*
- X * Failed pings is zero...
- X */
- X np->np_ping = 0;
- X
- X /*
- X * Recompute portmap information if not known
- X */
- X if (np->np_error < 0) {
- X if (!nfs_auth)
- X nfs_auth = authunix_create_default();
- X if (!nfs_auth)
- X np->np_error = ENOBUFS;
- X else
- X call_portmap(fs, nfs_auth, MOUNTPROG,
- X MOUNTVERS, (unsigned long) IPPROTO_UDP);
- X }
- X found_map++;
- X break;
- X }
- X }
- X
- X#ifdef DEBUG
- X if (found_map == 0)
- X dlog("Spurious ping packet");
- X#endif
- X}
- X
- X
- X/*
- X * Keep track of whether a server is alive
- X */
- Xstatic void nfs_keepalive(fs)
- Xfserver *fs;
- X{
- X int error;
- X nfs_private *np = (nfs_private *) fs->fs_private;
- X int fstimeo;
- X
- X /*
- X * Send an NFS ping to this node
- X */
- X
- X if (ping_len == 0)
- X start_ping();
- X
- X /*
- X * Queue the packet...
- X */
- X error = fwd_packet(MK_RPC_XID(RPC_XID_NFSPING, np->np_xid), (voidp) ping_buf,
- X ping_len, fs->fs_ip, (struct sockaddr_in *) 0, (voidp) np->np_xid, nfs_pinged);
- X
- X /*
- X * See if a hard error occured
- X */
- X switch (error) {
- X case ENETDOWN:
- X case ENETUNREACH:
- X case EHOSTDOWN:
- X case EHOSTUNREACH:
- X np->np_ping = MAX_ALLOWED_PINGS; /* immediately down */
- X break;
- X
- X case 0:
- X#ifdef DEBUG
- X dlog("Sent NFS ping to %s", fs->fs_host);
- X#endif
- X break;
- X }
- X
- X /*
- X * If N pings have failed then guess that it is dead
- X */
- X if (np->np_ping >= MAX_ALLOWED_PINGS) {
- X if (!(fs->fs_flags & FSF_VALID)) {
- X /*
- X * Starts off down
- X */
- X plog(XLOG_INFO, "file server %s type nfs starts down", fs->fs_host);
- X fs->fs_flags |= FSF_VALID;
- X if (fs->fs_flags & FSF_WANT)
- X wakeup_srvr(fs);
- X }
- X
- X if ((fs->fs_flags & FSF_DOWN) == 0) {
- X /*
- X * Server was up, but is now down.
- X */
- X plog(XLOG_INFO, "file server %s type nfs is down", fs->fs_host);
- X fs->fs_flags |= FSF_DOWN;
- X if (fs->fs_flags & FSF_WANT)
- X wakeup_srvr(fs);
- X /*
- X * Since the server is down, the portmap
- X * information may now be wrong, so it
- X * must be flushed from the local cache
- X */
- X flush_fhandle_cache(fs);
- X np->np_error = -1;
- X np->np_ping = 1;
- X }
- X } else {
- X np->np_ping++;
- X#ifdef DEBUG
- X if (np->np_ping > 1)
- X dlog("%d pings to %s failed - max %d allowed", np->np_ping, fs->fs_host, MAX_ALLOWED_PINGS);
- X#endif
- X }
- X
- X /*
- X * Back off the ping interval if we are not getting replies and
- X * the remote system is know to be down.
- X */
- X switch (fs->fs_flags & (FSF_DOWN|FSF_VALID)) {
- X case FSF_VALID: /* Up */
- X fstimeo = fs->fs_pinger;
- X break;
- X case FSF_VALID|FSF_DOWN: /* Down */
- X fstimeo = np->np_ping * fs->fs_pinger;
- X break;
- X default: /* Unknown */
- X fstimeo = FAST_NFS_PING;
- X break;
- X }
- X fs->fs_cid = timeout(fstimeo, nfs_keepalive, (voidp) fs);
- X}
- X
- Xint nfs_srvr_port(fs, port, wchan)
- Xfserver *fs;
- Xu_short *port;
- Xvoidp wchan;
- X{
- X int error = -1;
- X if ((fs->fs_flags & FSF_VALID) == FSF_VALID) {
- X if ((fs->fs_flags & FSF_DOWN) == 0) {
- X nfs_private *np = (nfs_private *) fs->fs_private;
- X if (np->np_error == 0) {
- X *port = np->np_mountd;
- X /*
- X * Now go get it again in case it changed
- X */
- X np->np_error = -1;
- X error = 0;
- X } else {
- X error = np->np_error;
- X }
- X } else {
- X error = EWOULDBLOCK;
- X }
- X }
- X if (error < 0 && wchan && !(fs->fs_flags & FSF_WANT)) {
- X /*
- X * If a wait channel is supplied, and no
- X * error has yet occured, then arrange
- X * that a wakeup is done on the wait channel,
- X * whenever a wakeup is done on this fs node.
- X * Wakeup's are done on the fs node whenever
- X * it changes state - thus causing control to
- X * come back here and new, better things to happen.
- X */
- X fs->fs_flags |= FSF_WANT;
- X sched_task(wakeup_task, wchan, (voidp) fs);
- X }
- X return error;
- X}
- X
- Xstatic void start_nfs_pings(fs)
- Xfserver *fs;
- X{
- X if (!(fs->fs_flags & FSF_PINGING)) {
- X fs->fs_flags |= FSF_PINGING;
- X if (fs->fs_cid)
- X untimeout(fs->fs_cid);
- X nfs_keepalive(fs);
- X } else {
- X#ifdef DEBUG
- X dlog("Already running pings to %s", fs->fs_host);
- X#endif
- X }
- X}
- X
- X/*
- X * Find an nfs server for a host.
- X */
- Xfserver *find_nfs_srvr(mf)
- Xmntfs *mf;
- X{
- X fserver *fs;
- X struct hostent *hp = 0;
- X char *host = mf->mf_fo->opt_rhost;
- X struct sockaddr_in *ip;
- X nfs_private *np;
- X
- Xtop:
- X /*
- X * Scan the list of known servers looking
- X * for one with the same name
- X */
- X ITER(fs, fserver, &nfs_srvr_list) {
- X if (STREQ(host, fs->fs_host)) {
- X start_nfs_pings(fs);
- X fs->fs_refc++;
- X return fs;
- X }
- X }
- X
- X /*
- X * If the name is not known, it may be
- X * because it was an alternate name for
- X * the same machine. So do a lookup and
- X * try again with the primary name if that
- X * is different.
- X * All that assuming it wasn't normalized
- X * earlier of course...
- X */
- X if (hp == 0) {
- X hp = gethostbyname(host);
- X if (hp && !STREQ(host, hp->h_name) && !normalize_hosts) {
- X host = hp->h_name;
- X goto top;
- X }
- X }
- X
- X /*
- X * Get here if we can't find an entry
- X */
- X if (hp) {
- X switch (hp->h_addrtype) {
- X case AF_INET:
- X ip = ALLOC(sockaddr_in);
- X bzero((voidp) ip, sizeof(*ip));
- X ip->sin_family = AF_INET;
- X ip->sin_addr = *(struct in_addr *) hp->h_addr;
- X ip->sin_port = htons(NFS_PORT);
- X break;
- X
- X default:
- X ip = 0;
- X break;
- X }
- X } else {
- X ip = 0;
- X }
- X
- X /*
- X * Allocate a new server
- X */
- X fs = ALLOC(fserver);
- X fs->fs_refc = 1;
- X fs->fs_host = strdup(hp ? hp->h_name : "unknown_hostname");
- X fs->fs_ip = ip;
- X fs->fs_cid = 0;
- X if (ip) {
- X fs->fs_flags = FSF_DOWN; /* Starts off down */
- X } else {
- X fs->fs_flags = FSF_ERROR|FSF_VALID;
- X mf->mf_flags |= MFF_ERROR;
- X mf->mf_error = ENOENT;
- X }
- X fs->fs_pinger = AM_PINGER;
- X np = ALLOC(nfs_private);
- X np->np_xid = NPXID_ALLOC();
- X bzero((voidp) np, sizeof(*np));
- X np->np_error = -1;
- X fs->fs_private = (voidp) np;
- X fs->fs_prfree = free;
- X
- X if (!(fs->fs_flags & FSF_ERROR)) {
- X /*
- X * Start of keepalive timer
- X */
- X start_nfs_pings(fs);
- X }
- X
- X /*
- X * Add to list of servers
- X */
- X ins_que(&fs->fs_q, &nfs_srvr_list);
- X
- X return fs;
- X}
- END_OF_FILE
- if test 11929 -ne `wc -c <'srvr_nfs.c'`; then
- echo shar: \"'srvr_nfs.c'\" unpacked with wrong size!
- fi
- # end of 'srvr_nfs.c'
- fi
- echo shar: End of archive 8 \(of 13\).
- cp /dev/null ark8isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 13 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- exit 0 # Just in case...
-